module if_stage#(
  parameter [31:0] BOOT_ADDR = 32'b0
)(
  input clk,
  input rst_n,

  input         ctrl_if_stall,
  input         ctrl_if_flush,
  input         ctrl_if_jmp_ena,
  input  [31:0] ctrl_if_jmp_target,

  output [31:0] if_mem_addr,
  input  [31:0] if_mem_inst,

  output reg        if_id_vld,
  output reg [31:0] if_id_inst,
  output reg [31:0] if_id_pc

);
  
  wire        pc_stall;
  wire [31:0] pc_next;

  assign pc_stall = ctrl_if_stall;

  pc_gen#(
    .BOOT_ADDR(BOOT_ADDR)
  ) pc_gen_inst (
    .clk(clk),
    .rst_n(rst_n),
    .pc_current(if_id_pc),
    .pc_stall(pc_stall),
    .pc_jmp_ena(ctrl_if_jmp_ena),
    .pc_jmp_addr(ctrl_if_jmp_target),
    .pc_next(pc_next)
  );

  assign if_mem_addr = pc_next;

  wire update_en;
  assign update_en = ~ctrl_if_stall;

  always @(posedge clk, negedge rst_n) begin
    if (~rst_n) begin
      if_id_vld <= 1'b0;
    end else if (~ctrl_if_stall) begin
      if_id_vld <= 1'b1;
    end else begin
      if_id_vld <= 1'b0;
    end
  end

  always @(posedge clk, negedge rst_n) begin
    if (~rst_n) begin
      if_id_pc <= 32'b0;
    end else if (update_en) begin
      if_id_pc <= pc_next;
    end
  end

  always @(posedge clk, negedge rst_n) begin
    if (~rst_n) begin
      if_id_inst <= 32'b0;
    end else if (update_en) begin
      if_id_inst <= if_mem_inst;
    end
  end

endmodule

